﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using BoYuanCore.CoreCodeTemplates.DBMappingRules;
using BoYuanCore.CoreCodeTemplates.FineUICore;
using FreeSql;
using FreeSql.DatabaseModel;

namespace BoYuanCore.CoreCodeTemplates.FreeSql
{
    public class EntityTemplate:FineUIBase
    {
        public static string GetCode(TableModel tb,string parentClass= "SnowflakEntity")
        {
            var columnList = tb.Columns;
            StringBuilder sb = new StringBuilder();//PropertyName  //字段属性
            StringBuilder sb2 = new StringBuilder();//Constructor  //构造里默认值
            for (int i = 0; i < columnList.Count; i++)
            {
                if (!columnList[i].IsPrimaryKey)//雪花id，主键不需要生成
                {
                    sb.AppendLine("        ///<summary>");
                    sb.AppendLine("        ///Desc:" + columnList[i].Coment);
                    sb.AppendLine("        ///Default:" + columnList[i].DefaultValue);
                    sb.AppendLine("        ///Nullable:" + columnList[i].IsNullable.ToString());
                    sb.AppendLine("        ///</summary>");
                    sb.Append(GetFreeSqlColumnInfo(columnList[i]));
                    sb.AppendLine("        public " + DataTypeMapping.Csharp.GetCsharpKeyword(columnList[i].CsType.Name) + " " + (columnList[i].DbColumnNameToClassName) + " { get; set; }");
                    sb.AppendLine("");
                }
                else //主键 
                {
                    if (parentClass != "SnowflakEntity")//非雪花主键
                    {
                        sb.AppendLine("        ///<summary>");
                        sb.AppendLine("        ///Desc:" + columnList[i].Coment);
                        sb.AppendLine("        ///Default:" + columnList[i].DefaultValue);
                        sb.AppendLine("        ///Nullable:" + columnList[i].IsNullable.ToString());
                        sb.AppendLine("        ///</summary>");
                        sb.AppendLine("        [JsonProperty,Column(IsPrimary = true"+(columnList[i].IsIdentity? ",IsIdentity = true" : string.Empty) +")]");
                        sb.AppendLine("        public " + DataTypeMapping.Csharp.GetCsharpKeyword(columnList[i].CsType.Name) + " " + (columnList[i].DbColumnNameToClassName) + " { get; set; }");
                        sb.AppendLine("");
                    }
                }

                if (!string.IsNullOrWhiteSpace(columnList[i].DefaultValue))//默认值
                {
                    string tempDefaultValue = GetDefaultValueCode(columnList[i], tb.DbClass);
                    if(tempDefaultValue.Length>0)
                        sb2.AppendLine("             this."+ (columnList[i].DbColumnNameToClassName) + " = "+ tempDefaultValue + ";");
                }
                
            }

            string code = string.Format(@"
using System;
using Newtonsoft.Json;
using FreeSql.DataAnnotations;

namespace {1}
{{
    ///<summary>
    ///{4}
    ///</summary>
    [Table(Name = ""{6}"")]
    [Serializable]
    [JsonObject(MemberSerialization.OptIn)]
    public partial class {0} {5}
    {{
        public {0}()
        {{
{3}
        }}

{2}

    }}
}}

"
            , tb.TableNameToClassName      //0
            , tb.NamespaceStr   //1
            , sb.ToString()     //2
            , sb2.ToString()    //3
            , GetTableDescription(tb)//4
            , string.IsNullOrEmpty(parentClass)?string.Empty:" : "+ parentClass //5
            , tb.TableName
);

            return code;
        }

        /// <summary>
        /// 获取表备注信息
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private static string GetTableDescription(TableModel table)
        {
            if (string.IsNullOrWhiteSpace(table.TableDescription))
            {
                //如果表备注信息没有，则获取主键信息
                var primaryKeyColumn = table.Columns.First(p => p.IsPrimaryKey);
                if (primaryKeyColumn == null)//如果主键为null，返回空字符串(不做无主键异常)
                {
                    return string.Empty;
                }
                else //个人习惯，可以把表备注信息写在主键备注里
                {
                    return primaryKeyColumn.Coment;
                }
            }
            else
            {
                return table.TableDescription;
            }
        }

        private static string GetFreeSqlColumnInfo(DbColumnInfo column)
        {
            switch (column.PropertyName)
            {
                case "string":
                    return "        [JsonProperty,Column(StringLength = " + column.MaxLength + ")]" + Environment.NewLine;
                case "datetime":
                    return "        [JsonProperty/*,Column(ServerTime = DefaultDateTimeKind)*/]" + Environment.NewLine;
                default:
                    return "        [JsonProperty]" + Environment.NewLine;
            }

            // switch (column.PropertyName.ToLower())
            // {
            //     case "char"://break;
            //     case "nchar"://break;
            //     case "varchar"://break;
            //     case "nvarchar":
            //         if (column.MaxLength > 0)
            //         {
            //             return GetFreeSqlColumnLengthInfo(column);
            //         }
            //         break;
            // }
        }

        private static string GetFreeSqlColumnLengthInfo(DbColumnInfo column)
        {
            //        [Column(Length = 20)]
            //经测试，nvarchar 等数据库类型，如果长度是nvarchar(50)，对应的column.Length是100。这个约定可能是CodeFirst 模式需要的，这里由于是DBFirst生成实体，需要改成50长度。
            int columnLength = column.MaxLength;
            if (column.DbTypeText.Substring(0, 1) == "n")
            {
                if ((column.MaxLength & 1) == 1) //奇数
                {
                    columnLength = (column.MaxLength - 1) / 2;
                }
                else
                {
                    columnLength = column.MaxLength / 2;
                }
            }
            //更改为FreeSql方式
            return "        [Column(StringLength = " + columnLength + ")]" + Environment.NewLine;
        }

        public static global::FreeSql.DatabaseModel.DbColumnInfo GetFreesqlDbColumnInfo(DbColumnInfo item)
        {
            global::FreeSql.DatabaseModel.DbColumnInfo freeColumnInfo = new global::FreeSql.DatabaseModel.DbColumnInfo();
            freeColumnInfo.Table = new DbTableInfo();
            freeColumnInfo.Table.Name = item.TableName;
            freeColumnInfo.Name = item.DbColumnNameToClassName;
            freeColumnInfo.CsType = item.CsType;
            freeColumnInfo.IsIdentity = item.IsIdentity;
            freeColumnInfo.IsNullable = item.IsNullable;
            freeColumnInfo.MaxLength = item.MaxLength;
            freeColumnInfo.Coment = item.Coment;
            freeColumnInfo.DefaultValue = item.DefaultValue;
            freeColumnInfo.IsPrimary = item.IsPrimaryKey;
            freeColumnInfo.DbTypeText = item.DbTypeText;
            freeColumnInfo.DbTypeTextFull = item.DbTypeTextFull;
            return freeColumnInfo;
        }

    }
}
